import * as Cesium from "cesium";
import * as turf from "@turf/turf";

class MarkTools {
    constructor(viewer) {
        this.viewer = viewer;
        this.handler = null;
        this.positions = [];
        this.tempPositions = [];
        this.drawingEntity = null;
        this.labelEntity = null;
        this.markType = null;
        this.tempPoints = [];
        this.init();
    }

    init() {
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    }

    // 清除测量
    clear() {
        if (this.handler) {
            this.handler.destroy();
            this.handler = null;
        }
        this.tempPoints = [];
        this.positions = [];
        this.tempPositions = [];
        this.markType = null;
    }

    // 开始测量
    start(type) {
        // 如果类型相同，不需要重新初始化
        if (this.markType === type && this.handler) {
            return;
        }
        this.markType = type;
        // 注册鼠标事件
        this.handler.setInputAction((movement) => {
            // 拾取地球表面的点
            const cartesian = this.getCartesian3FromPick(movement.position);
            if (!cartesian) return;

            // 添加点实体----画点
            this.addPoint(cartesian);
            this.positions.push(cartesian);

            // 对于点标注，第一个点后自动完成
            if (this.markType === 'point' && this.positions.length === 1) {
                this.finish();
                return;
            }

            // 创建或更新临时实体---画线
            if (this.positions.length === 1) {
                this.createTempEntity();
            }

            this.tempPositions = [...this.positions];
            this.updateTempEntity();

        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

        // 鼠标移动事件
        this.handler.setInputAction((movement) => {
            if (this.positions.length < 1) return;
            const cartesian = this.getCartesian3FromPick(movement.endPosition);
            if (!cartesian) return;

            // 只显示移动轨迹，不计入测量结果
            this.tempPositions = [...this.positions, cartesian];
            this.updateTempEntity(true); // 传入 true 表示是临时显示

        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        // 右键结束测量
        this.handler.setInputAction(() => {
            if (this.markType === 'line' && this.positions.length < 2) return;
            if (this.markType === 'polygon' && this.positions.length < 3) return;
            // 使用最后一个点击的位置作为最终结果
            this.tempPositions = [...this.positions];
            this.updateTempEntity();
            this.finish();
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    }

    // 获取地表坐标
    getCartesian3FromPick(windowPosition) {
        const ray = this.viewer.camera.getPickRay(windowPosition);
        return this.viewer.scene.globe.pick(ray, this.viewer.scene);
    }

    // 添加点实体
    addPoint(position) {
        const point = this.viewer.entities.add({
            position: position,
            point: {
                pixelSize: 15,
                color: Cesium.Color.RED.withAlpha(0.9),
                outlineColor: Cesium.Color.WHITE,
                outlineWidth: 2,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                disableDepthTestDistance: Number.POSITIVE_INFINITY
            }
        });

        // 只为非高程测量起点添加序号标签
        if (this.markType != 'point') {
            point.label = {
                text: (this.positions.length + 1).toString(),
                font: 'bold 12px sans-serif',
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                fillColor: Cesium.Color.WHITE,
                outlineColor: Cesium.Color.BLACK,
                outlineWidth: 2,
                verticalOrigin: Cesium.VerticalOrigin.CENTER,
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                disableDepthTestDistance: Number.POSITIVE_INFINITY,
                pixelOffset: new Cesium.Cartesian2(0, 0),
                scaleByDistance: new Cesium.NearFarScalar(1.0e2, 1.0, 1.0e7, 1.0)
            };
        }

        this.tempPoints.push(point);
    }

    // 创建临时实体
    createTempEntity() {
        if (this.markType === 'line') {
            this.drawingEntity = this.viewer.entities.add({
                polyline: {
                    positions: new Cesium.CallbackProperty(() => {
                        return this.tempPositions;
                    }, false),
                    width: 4,
                    material: new Cesium.PolylineDashMaterialProperty({
                        color: Cesium.Color.YELLOW
                    }),
                    clampToGround: true
                }
            });
        } else if (this.markType === 'polygon') {
            this.drawingEntity = this.viewer.entities.add({
                polygon: {
                    hierarchy: new Cesium.CallbackProperty(() => {
                        return new Cesium.PolygonHierarchy(this.tempPositions);
                    }, false),
                    material: Cesium.Color.YELLOW.withAlpha(0.4),
                    outline: true,
                    outlineColor: Cesium.Color.YELLOW
                }
            });
        }
    }

    // 更新临时实体
    updateTempEntity(isTemp = false) {
        if (!this.drawingEntity) return;

        // 更新测量结果标签
        let markResult = '';
        if (this.markType === 'line') {
            const distance = isTemp ? this.getDistance(this.tempPositions) : this.getDistance(this.positions);
            markResult = `总距离: ${distance}`;
        } else if (this.markType === 'polygon') {
            const area = isTemp ? this.getArea(this.tempPositions) : this.getArea(this.positions);
            markResult = `面积: ${area}`;
        }

        // 更新或创建标签实体
        let labelPosition;
        if (this.markType === 'polygon') {
            // 面积测量的标签位置在多边形的重心
            labelPosition = this.getCenterOfGravityPoint(this.tempPositions);
        } else if (this.markType === 'line') {
            // 测量的标签位置在最后一个点
            labelPosition = this.tempPositions[this.tempPositions.length - 1];
        }

        if (!this.labelEntity) {
            this.labelEntity = this.viewer.entities.add({
                position: labelPosition,
                label: {
                    text: markResult,
                    font: "bold 16px sans-serif",
                    fillColor: Cesium.Color.RED,
                    outlineColor: Cesium.Color.WHITE,
                    outlineWidth: 2,
                    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                    pixelOffset: new Cesium.Cartesian2(0, -30),
                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                    disableDepthTestDistance: Number.POSITIVE_INFINITY,
                    backgroundColor: Cesium.Color.BLACK.withAlpha(0.5)
                }
            });
        } else {
            this.labelEntity.position = labelPosition;
            this.labelEntity.label.text = markResult;
        }
    }


    // 计算距离
    getDistance(positions = this.positions) {

        if (positions.length < 2) return '0 米';

        let totalDistance = 0;
        // 遍历所有点，计算相邻两点之间的距离
        for (let i = 0; i < positions.length - 1; i++) {
            // 将 Cartesian3 坐标转换为经纬度
            const from = Cesium.Cartographic.fromCartesian(positions[i]);
            const to = Cesium.Cartographic.fromCartesian(positions[i + 1]);

            // 创建 turf 点
            const fromPoint = turf.point([
                Cesium.Math.toDegrees(from.longitude),
                Cesium.Math.toDegrees(from.latitude)
            ]);
            const toPoint = turf.point([
                Cesium.Math.toDegrees(to.longitude),
                Cesium.Math.toDegrees(to.latitude)
            ]);

            // 计算距离（单位：千米）
            const segmentDistance = turf.distance(fromPoint, toPoint, { units: 'kilometers' });
            totalDistance += segmentDistance;
        }

        // 格式化输出
        if (totalDistance < 1) {
            return (totalDistance * 1000).toFixed(2) + " 米";
        } else {
            return totalDistance.toFixed(2) + " 千米";
        }
    }

    // 获取多边形
    getPolygon(positions) {
        // 将 Cartesian3 坐标转换为经纬度数组
        let coordinates = positions.map(point => {
            // 将 Cartesian3 转换为经纬度
            const cartographic = Cesium.Cartographic.fromCartesian(point);
            const longitude = Cesium.Math.toDegrees(cartographic.longitude);
            const latitude = Cesium.Math.toDegrees(cartographic.latitude);
            return [longitude, latitude];
        });

        // 确保多边形闭合（首尾点相同）
        if (coordinates[0][0] !== coordinates[coordinates.length - 1][0] ||
            coordinates[0][1] !== coordinates[coordinates.length - 1][1]) {
            coordinates.push(coordinates[0]);
        }
        // 创建 turf.js 多边形
        return turf.polygon([coordinates]);
    }


    //计算多边形面积
    getArea(points) {
        if (points.length < 3) return '0 平方米';

        const polygon = this.getPolygon(points);

        // 计算面积（平方米）
        let res = turf.area(polygon);

        if (res < 1000000) {
            res = Math.abs(res).toFixed(4) + " 平方米";
        } else {
            res = Math.abs((res / 1000000.0).toFixed(4)) + " 平方公里";
        }
        return res;

    };

    /**
     * 计算多边形的重心
     * @param {Array} mPoints - 多边形顶点的笛卡尔坐标数组
     * @returns {Cesium.Cartesian3} 重心点的笛卡尔坐标
     */
    getCenterOfGravityPoint(mPoints) {
        if (!mPoints || mPoints.length < 3) {
            return mPoints[mPoints.length - 1];
        }
        // 使用turf.js计算重心
        const polygon = this.getPolygon(mPoints);
        // 计算重心
        const center = turf.centerOfMass(polygon);

        // 计算平均高度
        const avgHeight = mPoints.reduce((sum, point) => {
            return sum + Cesium.Cartographic.fromCartesian(point).height;
        }, 0) / mPoints.length;

        // 将重心点转换回笛卡尔坐标
        return Cesium.Cartesian3.fromDegrees(
            center.geometry.coordinates[0],
            center.geometry.coordinates[1],
            avgHeight
        );
    }

    // 完成测量
    finish() {
        // 如果不是临时显示，将实体添加到测量实体数组中
        // 将当前实体添加到测量实体数组中
        // 创建一个永久的测量实体（复制当前的临时实体）
        let permanentEntity;
        if (this.markType === 'point') {
            permanentEntity = this.viewer.entities.add({
                position: this.positions[0],
                point: {
                    pixelSize: 15,
                    color: Cesium.Color.RED.withAlpha(0.9),
                    outlineColor: Cesium.Color.WHITE,
                    outlineWidth: 2,
                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                    disableDepthTestDistance: Number.POSITIVE_INFINITY
                }
            });
        }

        if (this.markType === 'line') {
                permanentEntity = this.viewer.entities.add({
                    polyline: {
                        positions: this.positions,
                        width: 4,
                        material: new Cesium.PolylineDashMaterialProperty({
                            color: Cesium.Color.YELLOW
                        }),
                        clampToGround: true
                    }
                });
            } else if (this.markType === 'polygon') {
                permanentEntity = this.viewer.entities.add({
                    polygon: {
                        hierarchy: new Cesium.PolygonHierarchy(this.positions),
                        material: Cesium.Color.YELLOW.withAlpha(0.4),
                        outline: true,
                        outlineColor: Cesium.Color.YELLOW
                    }
                });
            }

         // 清除当前的临时点
        this.tempPoints.forEach(point => {
            this.viewer.entities.remove(point);
        });

         // 清除当前正在测量的临时实体
        if (this.drawingEntity) {
            this.viewer.entities.remove(this.drawingEntity);
            this.drawingEntity = null;
        }

        // 保留当前测量结果，只重置变量以准备下一次测量
        this.positions = [];
        this.tempPositions = [];
        this.tempPoints = [];

        // 只将它置为 null 以便下一次测量创建新的实体
        this.labelEntity = null;
    }
}

export default MarkTools; 
